package com.acme.bankapp.domain.bank;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.acme.bankapp.domain.client.Client;
import com.acme.bankapp.exceptions.ClientExistsException;

/**
 * Class contains the bank representation.
 *
 * @author S.Zhidkov
 */
public class Bank implements Serializable {

    private static final String ERROR_CLIENT_EXISTS = "Client already exists!";

    private List<Client> clients = new ArrayList<Client>();
    private List<ClientRegistrationListener> listeners = new ArrayList<ClientRegistrationListener>();

    /**
     * Create bank with registered listeners
     * @param listeners
     */
    public Bank(List<ClientRegistrationListener> listeners) {
        this.listeners = listeners;
    }

    /**
     * Create bank without listeners.
     */
    public Bank() {

    }

    /**
     * Class prints client each time client added into bank.
     */
    public static class PrintClientListener implements ClientRegistrationListener, Serializable {

        private static final String MESSAGE_CLIENT_ADDED = "Added client: ";

        @Override
        public void onClientAdded(Client client) {
            System.out.print(MESSAGE_CLIENT_ADDED);
            System.out.println(client);
        }
    }

    /**
     * Class sends e-mail each time client added into bank.
     */
    public static class EmailNotificationListener implements ClientRegistrationListener, Serializable {

        private static final String MESSAGE_NOTIFICATION1 = "Notification email for client ";
        private static final String MESSAGE_NOTIFICATION2 = " to be sent";

        @Override
        public void onClientAdded(Client client) {
            System.out.println(MESSAGE_NOTIFICATION1 + client + MESSAGE_NOTIFICATION2);
        }
    }

    /**
     * Class prints debug info - time and client info.
     */
    public static class DebugListener implements ClientRegistrationListener {
        private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

        @Override
        public void onClientAdded(Client client) {
            System.out.println(dateFormat.format(new Date()) + " >> " + client);
        }
    }

    /**
     * Get all clients of the bank
     * @return list of the clients
     */
    public List<Client> getClients() {
        return clients;
    }

    /**
     * Add client to the bank
     * @param client
     * @throws ClientExistsException
     */
    public void addClient(Client client) throws ClientExistsException {
        for (Client c : clients) {
            if (c.getName().equals(client.getName())) { throw new ClientExistsException(ERROR_CLIENT_EXISTS); }
        }

        clients.add(client);
        callListeners(client);
    }

    /**
     * Iterate through all registered listeners.
     *
     * @param client
     */
    private void callListeners(Client client) {
        for (ClientRegistrationListener listener : listeners) {
            if (listener != null) {
                listener.onClientAdded(client);
            }
        }
    }

    /**
     * Register new {@link ClientRegistrationListener}
     *
     * @param listener
     */
    public void addListener(ClientRegistrationListener listener) {
        listeners.add(listener);
    }

}
